package nivel;

import inteligenciaArtificial.ControladorBolasDeFuego;
import inteligenciaArtificial.ControladorEnemigos;
import inteligenciaArtificial.ControladorMonedas;
import inteligenciaArtificial.ControladorPowerUps;
import personaje.*;
import grafica.*;
import juego.*;
import logica.Logica;
import movimiento.MovimientoIA;

/**
 * Esta clase modela un stage determinado del juego. El juego no conoce al
 * tablero directamente, sino a través de el. Ventajas: - Mejor modularizacion
 * - Posibilidad de agregar niveles - Facilidad de carga - Manejo independiente
 * al juego
 * 
 * @author Agustin Orge (LU.85538)
 * @author Victoria Martinez de la Cruz (LU.87620)
 */
//
public class Nivel {

	/** El juego al que esta asociado el nivel */
	protected Juego juego;

	/** El tablero que modela las componentes del nivel */
	protected Tablero tab;

	/** El punaje del juego actual */
	protected Score score;

	/** La instancia de mario asociada al nivel */
	protected Mario mario;

	/** La gravedad que actua en el nivel */
	protected Gravedad gravedad;

	/** La visualizacion del nivel */
	protected GraficaNivel grafica;

	/** La logica utilizadas por todas las entidades con inteligencia artificial */
	protected Logica logicaAI;
	/** Movimiento */
	protected MovimientoIA movimiento;

	/** Controlador enemigos */
	protected ControladorEnemigos directorEnemigos;

	protected ControladorPowerUps directorPowerUps;

	/** Controlador monedas */

	protected ControladorMonedas controladorMonedas;
	
	/** Controlador bolas de fuego */
	protected ControladorBolasDeFuego controladorDisparos;

	/**
	 * Constructor de nivel. Recive el juego al que quedara asociado y se
	 * encarga de inicializar el Mario, la gravedad, el manejo de las
	 * componentes graficas, y la grafica del nivel
	 * 
	 * @param j
	 *            el juego
	 */
	public Nivel(Juego j) {
		tab = new Tablero();
		juego = j;
		score = juego.getScore();
		mario = new Mario(this);
		gravedad = new Gravedad(this);
		grafica = new GraficaNivel(this);
		logicaAI = new Logica();
		movimiento = new MovimientoIA();
		directorEnemigos = new ControladorEnemigos();
		directorPowerUps = new ControladorPowerUps();
		controladorMonedas = new ControladorMonedas(this);
		controladorDisparos = new ControladorBolasDeFuego();

	}
	/**
	 * Metodo que retorna el controlador de monedas
	 * @return controlador de monedas
	 */
	public ControladorMonedas getControladorMonedas() {
		return controladorMonedas;
	}


	/**
	 * Metodo utilizado para informale al nivel que el jugador perdio el nivel.
	 * Se encarga de eliminar el nivel para que no quede en ejecucion.
	 */
	public void perdioNivel() {
		score.disminuirVidas();
		juego.perdioNivel();
		try {
			finalize();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	/**
	 * Metodo que reporta a mario que debe morir
	 */
	public void murioMario() {
		mario.morir();
	}

	/**
	 * Metodo utilizado para informale al nivel que el jugador gano el nivel. Se
	 * encarga de eliminar el nivel para que
	 */
	public void ganoNivel() {
		juego.ganoNivel();

		try {
			finalize();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	

	/**
	 * Retorna el tablero que modela las componentes logicas del nivel
	 * 
	 * @return tablero
	 */
	public Tablero getTablero() {
		return tab;
	}

	/**
	 * Retorna el Mario asociado al nivel
	 * 
	 * @return mario
	 */
	public Mario getMario() {
		return mario;
	}

	/**
	 * Retorna la grafica del nivel
	 * 
	 * @return grafica nivel
	 */
	public GraficaNivel getGrafica() {
		return grafica;
	}

	/**
	 * Retorna la gravedad asociada al nivel
	 * 
	 * @return gravedad
	 */
	public Gravedad getGravedad() {
		return gravedad;
	}

	/**
	 * Retorna la logica, de las entidades con inteligencia artificial, asociada
	 * al nivel
	 * 
	 * @return logica
	 */
	public Logica getLogicaIA() {
		return logicaAI;
	}

	/**
	 * Retorna el objeto encargado de mover las entidades asociadas al nivel
	 * 
	 * @return movimiento
	 */
	public MovimientoIA getMovimiento() {
		return movimiento;
	}

	/**
	 * Retorna el director de enemigos
	 * 
	 * @return director de los enemigos
	 */
	public ControladorEnemigos getDirectorEnemigos() {
		return directorEnemigos;
	}
	/**
	 * Metodo que retorna el controlador de power ups
	 * @return controlador de power ups
	 */
	public ControladorPowerUps getDirectorPowerUps() {
		return directorPowerUps;
	}
	/**
	 * Metodo que retorna el controlador de bolas de fuego
	 * @return controlador de bolas de fuego
	 */
	public ControladorBolasDeFuego getControladorDisparos() {
		return controladorDisparos;
	}

	/**
	 * Retorna el score
	 * 
	 * @return puntaje
	 */
	public Score getScore() {
		return score;
	}
	/**
	 * Metodo utilizado para cortar la ejecucion de los bucles
	 * que realizan los hilos
	 */
	public void frenarHilos() {
		getGravedad().threadDone();
		getDirectorEnemigos().terminarHilo();
		getDirectorPowerUps().terminarHilo();

	}

}
